// Version 0.2.0
document.title += " with forms";

enum formModes {
    newForm = 0,
    displayForm = 1,
    editForm = 2
}

//#region  SPForm
class SPFormField {
    Comment: string;
    FieldName: string;
    FieldInternalName: string;
    FieldType: string;
    FormField: string;
    Value: any;

    Selector: any;
    JQPart: any;
    JQTable: any;
    JQRow: any;
    JQCell: any;
    JQTitleCell: any;
    JQTitle: any;
    JQInputField: any;

    constructor(selector: any) {
        this.Comment = "<!--" + $(selector)[0].nodeValue + "-->";

        var arrInfo = this.Comment.replace(/\t/g, "").replace(/\r/g, "").split("\n");
        this.FieldName = arrInfo[0].split("=")[1].replace(/"/g, "");
        this.FieldInternalName = arrInfo[1].split("=")[1].replace(/"/g, "");
        this.FieldType = arrInfo[2].split("=")[1].replace(/"/g, "");

        this.Selector = selector;
        if (this.Selector.nextSibling.nodeType == 3) {
            $(this.Selector.nextSibling).text();
        }
        else {
            this.FormField = $(this.Selector).next()[0].outerHTML;
        }

        this.JQCell = $(this.Selector).parent();
        this.JQTitleCell = this.JQCell.prev();
        this.JQTitle = this.JQTitleCell.find(".ms-standardheader");
        this.JQRow = $(this.Selector).parent().parent();
        this.JQTable = $(this.Selector).parent().parent().parent().parent();
        this.JQPart = $(this.Selector).parent().parent().parent().parent().parent();

        switch (this.FieldType) {
            case "SPFieldUser":
                this.JQInputField = this.JQCell.find(".ms-inputuserfield:first")
                break;
            default:
                this.JQInputField = $(this.Selector).next().find("input:first");
                if (this.JQInputField.length === 0) {
                    this.Value = this.JQCell.html();
                }
                else {
                    this.Value = this.JQInputField.val();
                }
                break;
        }
    }

    ValidationError(message: string) {
        $("#error" + this.FieldInternalName).remove();
        this.JQCell.append("<SPAN id=error" + this.FieldInternalName + " class=ms-formvalidation role=alert>" + message + "</SPAN>");
    }

    SetTitle(title: string) {
        this.JQTitle.html(title);
    }

    Hide() {
        this.JQRow.hide();
    }

    Show() {
        this.JQRow.show();
    }

    SetValue(value: any) {
        switch (this.FieldType) {
            case "SPFieldBoolean":
                this.JQInputField.prop('checked', value);

                break;
            case "SPFieldUser":
                this.JQInputField.html(value)
                break;
            case "SPFieldURL":
                if (value.indexOf("|") > -1) {
                    this.JQInputField.val(value.split("|")[0]);
                    this.JQCell.find('input').eq(1).val(value.split("|")[1]);
                }
                else {
                    this.JQInputField.val(value);
                    this.JQCell.find('input').eq(1).val(value);
                }
                break;
            default:
                this.JQInputField.val(value);
                break;
        }
    }

    HtmlDecode() {
        this.JQCell.html(this.Comment + htmlDecode(this.Value));
    }
}

class SPForm {
    Fields: any;
    Tabs: any;
    FormMode: formModes;
    JQPart: any;
    JQTable: any;
    JQInfoTable: any;
    JQSaveButton: any;
    JQCloseButton: any;
    JQToolbar: any;

    constructor() {
        this.Fields = GetSPFields();
        if (SPListExtractor.getFirst(this.Fields) != undefined) {
            this.JQPart = this.Fields[SPListExtractor.getFirst(this.Fields)].JQPart;
            this.JQTable = this.Fields[SPListExtractor.getFirst(this.Fields)].JQTable;
            this.JQToolbar = this.JQPart.find("table.ms-toolbar:first");
            this.JQSaveButton = this.JQPart.find(".ms-toolbar input[id*='IOSave']");
            this.JQCloseButton = this.JQPart.find(".ms-toolbar input[id*='IOGoBack']");
            this.JQInfoTable = this.JQPart.find("td[id*=onetidinfoblock]:first");
            if (this.JQInfoTable.length > 0) {
                this.JQInfoTable = this.JQInfoTable.parent().parent().parent();
                if (this.JQSaveButton.length === 0) {
                    this.FormMode = formModes.displayForm;
                }
                else {
                    this.FormMode = formModes.editForm;
                }
            }
            else {
                this.FormMode = formModes.newForm;
            }


            this.Tabs = new Array();
            this.Tabs["General"] = new SPFormTab("General", "Generel", this.Fields);
        }
    }

    HtmlDecode() {
        for (key in this.Fields) {
            this.Fields[key].HtmlDecode();
        }
    }

    ShowTabs() {
        var tabHTML = "<style>.formTab > ul > .ms-cui-tt > .ms-cui-tt-a {color:black !important;}</style>";
        tabHTML += "<div class='formTab'><UL class=ms-cui-tts>"
		for (var tab in this.Tabs) {
            if ((this.Tabs[tab] != undefined) && !(SPListExtractor.isFunction(this.Tabs[tab]))) {
                tabHTML += "<LI class='ms-cui-tt ms-browseTab' id='tab" + this.Tabs[tab].TabInternalName + "'><A class=ms-cui-tt-a onclick='$(\".TabAll\").hide();$(\"." + this.Tabs[tab].TabInternalName + "\").show();$(\".formTab > ul > .ms-browseTab\").removeClass(\"ms-cui-tt-s\");$(\"#tab" + this.Tabs[tab].TabInternalName + "\").addClass(\"ms-cui-tt-s\");return false;' href='javascript:;' ><SPAN class=ms-cui-tt-span unselectable='on'>" + this.Tabs[tab].Title + "</SPAN></A></LI>";
                $("." + this.Tabs[tab].TabInternalName + "").hide();
            }
        }

        tabHTML += "</UL></div>"
		this.JQPart.prepend(tabHTML);
        $("." + this.Tabs[SPListExtractor.getFirst(this.Tabs)].TabInternalName + "").show();
        $("#tab" + this.Tabs[SPListExtractor.getFirst(this.Tabs)].TabInternalName + "").addClass("ms-cui-tt-s");
    }
}

class SPFormTab {
    TabInternalName: string;
    Title: string;
    Fields: any;
    constructor(internalName: string, title: string, fields) {
        this.TabInternalName = internalName;
        this.Title = title;
        if (fields == null) {
            this.Fields = new Array();
        }
        else {
            this.Fields = fields;
            for (var i in this.Fields) {
                if (this.Fields[i].JQRow != undefined) {
                    this.Fields[i].JQRow.addClass(this.TabInternalName + " TabAll");
                }
            }
        }
    }
    MoveFieldsToTab(fields: any, tab: any) {
        for (var i = 0; i < fields.length; i++) {
            tab.AddField(this.Fields[fields[i]]);
            this.RemoveField(this.Fields[fields[i]]);
        }
    }

    AddField(field: any) {
        field.JQRow.addClass(this.TabInternalName);
        this.Fields[field.FieldInternalName] = field;
    }

    AddFields(fields: any) {
        for (var i = 0; i < fields.length; i++) {
            this.AddField(fields[i]);
        }
    }

    RemoveField(field: any) {
        field.JQRow.removeClass(this.TabInternalName);

    }

}
//#endregion  SPForm

function GetSPFields() {
    var returnValue = new Array();
    var tmpField;
    $("*").contents().filter(function () {
        return (this.nodeType === 8)
    }).each(function () {
            if (this.innerHTML.indexOf("FieldInternalName") > 0) {
                tmpField = new SPFormField(this);

                returnValue[tmpField.FieldInternalName] = tmpField;
            }
        });
    return returnValue;
}

function htmlEncode(value) {
    //create a in-memory div, set it's inner text(which jQuery automatically encodes)
    //then grab the encoded contents back out.  The div never exists on the page.
    return $('<div/>').text(value).html();
}

function htmlDecode(value) {
    return $('<div/>').html(value).text();
}